<?php

/**
 * Class for DB exception managing
 * @author Francesco
 *
 */

class DbException extends Exception{
	const CONNECTION_ERROR = 10;
	const QUERY_ERROR = 20;
	const GENERIC_ERROR = 30;
	const DB_ERROR = 40;
}

/**
 * Default framework db adpter class, use Mysqli php adapter
 * @author Francesco
 *
 */
class db{
	
	/**
	 * Contains the connection object, if is false, there is not connection
	 * @var mysqli
	 */
	private $con = false;
	
	/**
	 * Array with the result of a query statement
	 * @var array
	 */
	public $recordset = array();
	
	/**
	 * Last insert table id generated by an insert query
	 * @var int
	 */
	public $last_insert_id;
	
	/**
	 * Last updated table id generated by an update query
	 * @var int
	 */
	public $last_updated_id;
	
	/**
	 * Last registered error in db queries.
	 * @var mixed
	 */
	public $last_error;
	
	/**
	 * Number of affected rows by a query statement execution
	 * @var int
	 */
	public $affected_rows;
	
	/**
	 * Length of the recordset generated by a select statement
	 * @var int
	 */
	public $rs_count;
	
	/**
	 * Flag to determine if during a connection there's been an error
	 * @var unknown
	 */
	public $connection_error = false;
	
	/**
	 * Log of db errors
	 * @var mixed
	 */
	public $db_err_log;
	
	/**
	 * Hostname for db connection
	 * @var string
	 */
	private $db_host;
	
	/**
	 * Username for connection
	 * @var string
	 */
	private $db_user;
	
	/**
	 * Password for connection
	 * @var string
	 */
	private $db_password;
	
	/**
	 * Database name
	 * @var string
	 */
	private $db_name;
		
	/**
	 * Class constructor
	 * @throws DbException
	 */
	public function __construct(){
		try{
			if(defined('DB_HOST') && defined('DB_USER') && defined('DB_PASSWORD') && defined('DB_NAME')){
				$this->db_host = DB_HOST;
				$this->db_user = DB_USER;
				$this->db_password = DB_PASSWORD;
				$this->db_name = DB_NAME;
				$this->CheckCustomParams();
				$this->mysqli_connection();
			} else {
				throw new DbException('no db defined', DbException::CONNECTION_ERROR);
			}
		} catch(DbException $e){
			fb::log($e);
			$this->err_log = $e->getMessage();
		}
	}
	
	/**
	 * Close the connection before exit
	 * @throws DbException
	 */
	function __destruct(){
		if($this->con)$this->con->close();
		if(FIREBUG_DEBUG && !empty($this->last_error))throw new DbException('errore query:'.$this->last_error, DbException::QUERY_ERROR);
	}
	
	/**
	 * TODO : Implements the method for dynamic load custom connection params
	 */
	private function CheckCustomParams(){
		
	}
	
	/**
	 * Etablishment of a MySqlI Connection
	 * @throws DbException
	 */
	public function mysqli_connection(){
		if(!$this->con){
			$mysqli = new mysqli($this->db_host, $this->db_user, $this->db_password, $this->db_name);
			if ($mysqli->connect_errno) {
				throw new DbException('connection_failed', DbException::CONNECTION_ERROR);
			} else {
				$this->con = $mysqli;
			}
		}
	}
	
	/**
	 * Execute a standard query
	 * @param string $query
	 * @param boolean $object
	 * @return number|multitype:
	 */
	public function query($query, $object = false){
		$stmt = $this->con->query($query);
		if (!$stmt) {
			$this->last_error = $this->con->error;
		}
		$this->affected_rows = $this->con->affected_rows;
		if(substr($query, 0, 6) == "UPDATE" || substr($query, 0, 6) == "INSERT"){
			$this->last_updated_id = $this->con->insert_id;
			return $this->last_updated_id;
		}
		$rs = array();
		while($result = !$object ? $stmt->fetch_array(MYSQLI_ASSOC) : $stmt->fetch_object()){
			$this->recordset[]=$result;
		}
		return $this->recordset;
	}
	
	/**
	 * Execute a query on a table returning an object with the map
	 * of the selected table, respecting the passed limit. 
	 * @param string $table
	 * @param int $limit
	 * @return multitype:
	 */
	public function query_object($table, $limit = ""){
		$query = "SELECT * FROM ".$table;
		if(!empty($limit))$query .= " LIMIT ".$limit;
		$stmt = $this->con->query($query);
		if (!$stmt) {
			$this->last_error = $this->con->error;
		}
		$this->affected_rows = $this->con->affected_rows;
		if($this->affected_rows == 1){
			$this->recordset = $stmt->fetch_object();
		} else {
			while($result = $stmt->fetch_object()){
				$this->recordset[]=$result;
			}
		}
		return $this->recordset;
	}
	
	/**
	 * Return the current Db Connection
	 */
	public function getDbConnection(){
		return $this->con;
	}
	
	/**
	 * Return the max values on the passed db query
	 * @param string $query
	 * @param boolean $object
	 * @throws DbException
	 * @return multitype:
	 */
	public function query_max($query, $object = false){
		$stmt = $this->con->query($query);
		if (!$stmt) {
			$this->last_error = $this->con->error;
		}
		if(substr($query, 0, 6) == "UPDATE" || substr($query, 0, 6) == "INSERT"){
			throw new DbException('only_for_select', DbException::GENERIC_ERROR);
		}
		$this->affected_rows = $this->con->affected_rows;
		$rs = array();
		$this->recordset = !$object ? $stmt->fetch_array(MYSQLI_ASSOC) : $stmt->fetch_object();
		return $this->recordset;
	}
	
	public function get_last_insert_id(){
		$con = $this->getDbConnection();
		return $con ? $con->insert_id : false;
	}
	

}


?>
